package com.tony.common.struts;

import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

public class AutoAddingList implements java.util.List {
	private Class itemClass;

	private TreeMap map = new TreeMap();

	public AutoAddingList(Class itemClass) {
		this.itemClass = itemClass;
	}

	// public Object get(int index) {
	// try {
	// while (index >= size()) {
	// add(itemClass.newInstance());
	// }
	// } catch (Exception e) {
	// e.printStackTrace();
	// }
	// return super.get(index);
	// }
	public boolean addAll(Collection coll) {
		return this.addAll(0, coll);
	}

	public Object get(int index) {
		String ind = String.valueOf(index);
		Object obj = map.get(ind);
		try {
			if (obj == null) {
				Object target = itemClass.newInstance();
				map.put(ind, target);
				return map.get(ind);
			} else {
				return map.get(ind);
			}
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	
	public Object get(int index, boolean useExistingOnly){
		Iterator ite = map.values().iterator();
		int idx = 0;
		while(idx < index){
			ite.next();
			idx++;
		}
		return ite.next();
	}

	public boolean add(Object o) {
		int i = 0;
		while (map.get(String.valueOf(i)) != null) {
			i++;
		}
		this.map.put(String.valueOf(i), o);
		return true;
	}

	public void add(int index, Object element) {
		if (map.get(String.valueOf(index)) != null) {
			throw new IndexOutOfBoundsException(
					"invalid index value. that position already has object.");
		}
		map.put(String.valueOf(index), element);
	}

	public boolean addAll(int index, Collection c) {
		Iterator iter = c.iterator();
		int i = index;
		while (iter.hasNext()) {
			while (map.get(String.valueOf(i)) != null) {
				i++;
			}
			this.map.put(String.valueOf(i), iter.next());
		}
		return true;
	}

	public void clear() {
		this.map.clear();
	}

	public boolean contains(Object o) {
		return this.map.containsValue(o);
	}

	public boolean containsAll(Collection c) {
		throw new UnsupportedOperationException("not implemented yet.");
	}

	public int indexOf(Object o) {
		throw new UnsupportedOperationException("not implemented yet.");
	}

	public boolean isEmpty() {
		return this.map.isEmpty();
	}

	public Iterator iterator() {
		return map.values().iterator();
	}

	public int lastIndexOf(Object o) {
		throw new UnsupportedOperationException("not implemented yet.");
	}

	public ListIterator listIterator() {
		throw new UnsupportedOperationException("not implemented yet.");
	}

	public ListIterator listIterator(int index) {
		throw new UnsupportedOperationException("not implemented yet.");
	}

	public boolean remove(Object o) {
		// can not resolve ConcurrentModificationException
		throw new UnsupportedOperationException("not implemented yet.");
	}

	public Object remove(int index) {
		return map.remove(String.valueOf(index));
	}

	public boolean removeAll(Collection c) {
		for (Iterator iter = c.iterator(); iter.hasNext();) {
			this.remove(iter.next());
		}
		return true;
	}
	
	public boolean retainAll(Collection c) {
		throw new UnsupportedOperationException("not implemented yet.");
	}

	public Object set(int index, Object element) {
		this.map.remove(String.valueOf(index));
		return this.map.put(String.valueOf(index), element);
	}

	public int size() {
		return this.map.size();
	}

	public List subList(int fromIndex, int toIndex) {
		throw new UnsupportedOperationException("not implemented yet.");
	}

	public Object[] toArray() {
		return this.map.values().toArray();
	}

	public Object[] toArray(Object[] a) {
		return this.map.values().toArray();
	}
	
	public Collection values(){
		return this.map.values();
	}
	
	public static void main(String[] args) {
		AutoAddingList al = new AutoAddingList(StringBuffer.class);
		((StringBuffer)al.get(5)).append("first");
		((StringBuffer)al.get(6)).append("second");
		System.out.println(al.get(0,true).toString());
	}
}
